<template>
  <div class="dxf-viewer">
    <div class="controls">
      <input v-model="dxfUrl" placeholder="输入 DXF 文件 URL" />
      <button @click="loadRemoteDXF" :disabled="loading">
        {{ loading ? '加载中...' : '加载 DXF' }}
      </button>
      <button @click="resetView">重置视图</button>
    </div>
    <div ref="container" class="dxf-container">
      <div v-if="loading" class="loading">加载中...</div>
      <div v-if="error" class="error">{{ error }}</div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as THREE from 'three'
import DxfParser from 'dxf-parser'

// 响应式数据
const container = ref(null)
const dxfUrl = ref('')
const loading = ref(false)
const error = ref('')

// Three.js 相关变量
let scene, camera, renderer, controls

// 初始化 Three.js 场景
const initThree = () => {
  if (!container.value) return

  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0xf8f9fa)

  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    container.value.clientWidth / container.value.clientHeight,
    0.1,
    1000
  )
  camera.position.set(100, 100, 100)

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  })
  renderer.setSize(container.value.clientWidth, container.value.clientHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  container.value.appendChild(renderer.domElement)

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05

  // 添加光源
  const ambientLight = new THREE.AmbientLight(0x404040, 0.6)
  scene.add(ambientLight)

  const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8)
  directionalLight1.position.set(1, 1, 1)
  scene.add(directionalLight1)

  const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5)
  directionalLight2.position.set(-1, -1, -1)
  scene.add(directionalLight2)

  // 添加网格辅助
  const gridHelper = new THREE.GridHelper(100, 10)
  scene.add(gridHelper)

  const axesHelper = new THREE.AxesHelper(50)
  scene.add(axesHelper)

  // 动画循环
  const animate = () => {
    requestAnimationFrame(animate)
    controls.update()
    renderer.render(scene, camera)
  }
  animate()

  // 响应窗口大小变化
  window.addEventListener('resize', handleResize)
}

// 处理窗口大小变化
const handleResize = () => {
  if (!container.value || !camera || !renderer) return

  camera.aspect = container.value.clientWidth / container.value.clientHeight
  camera.updateProjectionMatrix()
  renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}

// 加载远程 DXF 文件
const loadRemoteDXF = async () => {
  if (!dxfUrl.value.trim()) {
    error.value = '请输入 DXF 文件 URL'
    return
  }

  loading.value = true
  error.value = ''

  try {
    // 获取 DXF 文件内容
    const response = await fetch(dxfUrl.value)
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const dxfContent = await response.text()

    // 清除之前的 DXF 内容
    clearDXFContent()

    // 解析并渲染 DXF
    await parseAndRenderDXF(dxfContent)

  } catch (err) {
    console.error('加载 DXF 文件失败:', err)
    error.value = `加载失败: ${err.message}`
  } finally {
    loading.value = false
  }
}

// 清除之前的 DXF 内容
const clearDXFContent = () => {
  if (!scene) return

  // 保留辅助对象（网格、坐标轴等）
  const toRemove = []
  scene.traverse(child => {
    if (child.userData && child.userData.isDXFEntity) {
      toRemove.push(child)
    }
  })

  toRemove.forEach(child => {
    scene.remove(child)
    if (child.geometry) child.geometry.dispose()
    if (child.material) child.material.dispose()
  })
}

// 解析并渲染 DXF
const parseAndRenderDXF = (dxfContent) => {
  try {
    const parser = new DxfParser()
    const dxf = parser.parseSync(dxfContent)

    if (!dxf.entities || dxf.entities.length === 0) {
      throw new Error('DXF 文件中没有找到实体')
    }

    // 创建边界框来计算视图
    const bbox = new THREE.Box3()

    // 渲染所有实体
    dxf.entities.forEach(entity => {
      const mesh = createEntityMesh(entity)
      if (mesh) {
        mesh.userData = { isDXFEntity: true }
        scene.add(mesh)

        // 更新边界框
        new THREE.Box3().setFromObject(mesh).expandByObject(mesh)
        bbox.expandByObject(mesh)
      }
    })

    // 调整相机视角
    if (!bbox.isEmpty()) {
      const center = bbox.getCenter(new THREE.Vector3())
      const size = bbox.getSize(new THREE.Vector3())
      const maxDim = Math.max(size.x, size.y, size.z)

      camera.position.copy(center).add(new THREE.Vector3(maxDim, maxDim, maxDim))
      controls.target.copy(center)
      controls.update()
    }

  } catch (err) {
    console.error('DXF 解析错误:', err)
    throw new Error(`DXF 解析失败: ${err.message}`)
  }
}

// 创建实体网格
const createEntityMesh = (entity) => {
  switch (entity.type) {
    case 'LINE':
      return createLine(entity)
    case 'CIRCLE':
      return createCircle(entity)
    case 'ARC':
      return createArc(entity)
    case 'LWPOLYLINE':
    case 'POLYLINE':
      return createPolyline(entity)
    case 'INSERT':
      return createInsert(entity)
    case 'TEXT':
      return createText(entity)
    default:
      console.warn(`未支持的实体类型: ${entity.type}`)
      return null
  }
}

// 创建线段
const createLine = (line) => {
  const material = new THREE.LineBasicMaterial({
    color: getEntityColor(line)
  })

  const points = [
    new THREE.Vector3(line.start.x, line.start.y, line.start.z || 0),
    new THREE.Vector3(line.end.x, line.end.y, line.end.z || 0)
  ]

  const geometry = new THREE.BufferGeometry().setFromPoints(points)
  return new THREE.Line(geometry, material)
}

// 创建圆
const createCircle = (circle) => {
  const material = new THREE.LineBasicMaterial({
    color: getEntityColor(circle)
  })

  const curve = new THREE.EllipseCurve(
    0, 0, // center
    circle.radius, circle.radius, // xRadius, yRadius
    0, 2 * Math.PI, // startAngle, endAngle
    false, // clockwise
    0 // rotation
  )

  const points = curve.getPoints(50)
  const geometry = new THREE.BufferGeometry().setFromPoints(
    points.map(p => new THREE.Vector3(p.x, p.y, circle.center.z || 0))
  )

  const circleLine = new THREE.Line(geometry, material)
  circleLine.position.set(circle.center.x, circle.center.y, 0)
  return circleLine
}

// 创建圆弧
const createArc = (arc) => {
  const material = new THREE.LineBasicMaterial({
    color: getEntityColor(arc)
  })

  const startAngle = (arc.startAngle * Math.PI) / 180
  const endAngle = (arc.endAngle * Math.PI) / 180

  const curve = new THREE.ArcCurve(
    0, 0, // center
    arc.radius,
    startAngle, endAngle,
    false // clockwise
  )

  const points = curve.getPoints(50)
  const geometry = new THREE.BufferGeometry().setFromPoints(
    points.map(p => new THREE.Vector3(p.x, p.y, arc.center.z || 0))
  )

  const arcLine = new THREE.Line(geometry, material)
  arcLine.position.set(arc.center.x, arc.center.y, 0)
  return arcLine
}

// 创建多段线
const createPolyline = (polyline) => {
  if (!polyline.vertices || polyline.vertices.length < 2) return null

  const material = new THREE.LineBasicMaterial({
    color: getEntityColor(polyline)
  })

  const points = polyline.vertices.map(vertex =>
    new THREE.Vector3(vertex.x, vertex.y, vertex.z || 0)
  )

  // 如果是闭合的，添加第一个点
  if (polyline.shape && points.length > 0) {
    points.push(points[0].clone())
  }

  const geometry = new THREE.BufferGeometry().setFromPoints(points)
  return new THREE.Line(geometry, material)
}

// 创建图块插入
const createInsert = (insert) => {
  // 简化处理：只显示插入点
  const material = new THREE.PointsMaterial({
    color: 0xff0000,
    size: 5
  })

  const geometry = new THREE.BufferGeometry()
  geometry.setAttribute('position', new THREE.Float32BufferAttribute([
    insert.position.x, insert.position.y, insert.position.z || 0
  ], 3))

  return new THREE.Points(geometry, material)
}

// 创建文字（简化处理）
const createText = (text) => {
  // 这里可以集成 three-text-geometry 等库来显示文字
  // 目前先用线段简单表示文字位置
  const material = new THREE.LineBasicMaterial({ color: 0x0000ff })
  const points = [
    new THREE.Vector3(text.position.x, text.position.y, text.position.z || 0),
    new THREE.Vector3(text.position.x + 10, text.position.y, text.position.z || 0)
  ]

  const geometry = new THREE.BufferGeometry().setFromPoints(points)
  return new THREE.Line(geometry, material)
}

// 获取实体颜色
const getEntityColor = (entity) => {
  // 可以根据 DXF 的图层或颜色索引来设置颜色
  if (entity.color) {
    return entity.color
  }

  // 默认颜色映射
  const colorMap = {
    'LINE': 0x0000ff,    // 蓝色
    'CIRCLE': 0xff0000,  // 红色
    'ARC': 0x00ff00,     // 绿色
    'LWPOLYLINE': 0x000000, // 黑色
    'POLYLINE': 0x000000,   // 黑色
  }

  return colorMap[entity.type] || 0x888888 // 默认灰色
}

// 重置视图
const resetView = () => {
  if (camera && controls) {
    camera.position.set(100, 100, 100)
    controls.target.set(0, 0, 0)
    controls.update()
  }
}

// 示例 DXF 文件 URL
const exampleUrls = [
  'https://example.com/path/to/your/file.dxf',
  'https://raw.githubusercontent.com/your-repo/sample.dxf'
]

// 生命周期
onMounted(() => {
  initThree()
  // 可以在这里设置一个默认的 DXF URL
  // dxfUrl.value = exampleUrls[0]
})

onUnmounted(() => {
  if (renderer) {
    renderer.dispose()
  }
  window.removeEventListener('resize', handleResize)
})
</script>

<style scoped>
.dxf-viewer {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.controls {
  padding: 10px;
  background: #fff;
  border-bottom: 1px solid #ddd;
  display: flex;
  gap: 10px;
  align-items: center;
}

.controls input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  max-width: 400px;
}

.controls button {
  padding: 8px 16px;
  border: 1px solid #007bff;
  background: #007bff;
  color: white;
  border-radius: 4px;
  cursor: pointer;
}

.controls button:disabled {
  background: #6c757d;
  border-color: #6c757d;
  cursor: not-allowed;
}

.controls button:not(:disabled):hover {
  background: #0056b3;
  border-color: #0056b3;
}

.dxf-container {
  flex: 1;
  position: relative;
  background: #f8f9fa;
}

.loading, .error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 20px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  z-index: 10;
}

.error {
  color: #dc3545;
  background: #f8d7da;
  border: 1px solid #f5c6cb;
}

.loading {
  color: #0c5460;
  background: #d1ecf1;
  border: 1px solid #bee5eb;
}
</style>